package com.cloudkinto.service.mail.impl;

import com.cloudkinto.entity.MailAccountDo;
import com.cloudkinto.service.mail.MailSenderService;
import com.cloudkinto.service.mail.vo.SendMailReq;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.*;
import javax.mail.internet.*;
import java.util.Properties;

/**
 * Author Administrator
 *
 * @Des
 * @Version
 * @Date 2019/9/26
 */
/*com.cloudkinto.service.mail.MailSenderService*/
@Service
public class MailSenderServiceImpl implements MailSenderService {
    private Logger logger = LoggerFactory.getLogger(getClass());

    @Override
//    @Async("asyncExecutor")
    public void sendEmail(String title, String content, String address) {
        logger.debug(Thread.currentThread().getName());
        try {
            Properties prop = new Properties();
            final String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory";
            prop.setProperty("mail.host", "smtp.exmail.qq.com");//这里设置了用qq邮箱发邮件
            prop.setProperty("mail.transport.protocol", "smtp");
            prop.setProperty("mail.smtp.auth", "true");
            prop.setProperty("mail.smtp.socketFactory.class", SSL_FACTORY);
            prop.setProperty("mail.smtp.socketFactory.fallback", "false");
            //邮箱发送服务器端口,这里设置为465端口
            prop.setProperty("mail.smtp.port", "465");
            prop.setProperty("mail.smtp.socketFactory.port", "465");
            //使用JavaMail发送邮件的5个步骤
            //1、创建session
            Session session = Session.getInstance(prop);
            //开启Session的debug模式，这样就可以查看到程序发送Email的运行状态
            session.setDebug(true);
            //2、通过session得到transport对象
            Transport ts = session.getTransport();
            //3、使用邮箱的用户名和密码连上邮件服务器，发送邮件时，发件人需要提交邮箱的用户名和密码给smtp服务器，用户名和密码都通过验证之后才能够正常发送邮件给收件人。
            ts.connect("smtp.exmail.qq.com", "ding@cloudkinto.com", "BkcYF5xn55fgb3c3");
            //4、创建邮件
            Message message = createSimpleMail(session, title, content, "ding@cloudkinto.com",address, "");
            //5、发送邮件
            ts.sendMessage(message, message.getAllRecipients());
            ts.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void transportClose(Transport ts) {
        try {
            ts.close();
        } catch (MessagingException e) {
            e.printStackTrace();
        }
    }

    @Override
    public Session initMailSession(SendMailReq req) {
        Properties prop = new Properties();
        final String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory";

        // 设置邮件服务器地址
        prop.setProperty("mail.host", req.getSmtp());

        // 设置传输协议
        prop.setProperty("mail.transport.protocol", "smtp");

        // 启用认证
        prop.setProperty("mail.smtp.auth", "true");

        // 动态设置端口号和加密方式
        if (req.getPort() != null && !req.getPort().isEmpty()) {
            int port = Integer.parseInt(req.getPort());
            prop.setProperty("mail.smtp.port", req.getPort());
            prop.setProperty("mail.smtp.socketFactory.port", req.getPort());

            if (port == 587) {
                // 如果端口号为 587，则启用 TLS 加密
                prop.setProperty("mail.smtp.starttls.enable", "true");
                prop.setProperty("mail.smtp.starttls.required", "true");
            } else if (port == 465) {
                // 如果端口号为 465，则使用 SSL 加密
                prop.setProperty("mail.smtp.socketFactory.class", SSL_FACTORY);
                prop.setProperty("mail.smtp.socketFactory.fallback", "false");
            }
        } else {
            // 默认使用 SSL 加密（端口 465）
            prop.setProperty("mail.smtp.port", "465");
            prop.setProperty("mail.smtp.socketFactory.port", "465");
            prop.setProperty("mail.smtp.socketFactory.class", SSL_FACTORY);
            prop.setProperty("mail.smtp.socketFactory.fallback", "false");
        }
        // 创建 Session 对象
        Session session = Session.getInstance(prop);

        // 开启调试模式
        session.setDebug(true);

        return session;
    }


   /* @Override
    public Session initMailSession(SendMailReq req) {
        Properties prop = new Properties();
        final String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory";
       // prop.setProperty("mail.host", "smtp.exmail.qq.com");//这里设置了用qq邮箱发邮件
        prop.setProperty("mail.host", req.getSmtp());//这里设置了用qq邮箱发邮件
        prop.setProperty("mail.transport.protocol", "smtp");
        prop.setProperty("mail.smtp.auth", "true");
        prop.setProperty("mail.smtp.socketFactory.class", SSL_FACTORY);
        prop.setProperty("mail.smtp.socketFactory.fallback", "false");
        //邮箱发送服务器端口,这里设置为465端口
        prop.setProperty("mail.smtp.port", "465");
        prop.setProperty("mail.smtp.socketFactory.port", "465");
        if (req.getPort() != null && !req.getPort().isEmpty()) {
            prop.setProperty("mail.smtp.port", req.getPort());
            prop.setProperty("mail.smtp.socketFactory.port", req.getPort());
        }

        //使用JavaMail发送邮件的5个步骤
        //1、创建session
        Session session = Session.getInstance(prop);
        //开启Session的debug模式，这样就可以查看到程序发送Email的运行状态
        session.setDebug(true);
        return session;
    }*/




    public Session initMailSession(MailAccountDo mailAccountDo) {
        Properties prop = new Properties();
        final String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory";
      //  prop.setProperty("mail.host", "smtp.exmail.qq.com");//这里设置了用qq邮箱发邮件
        prop.setProperty("mail.host", mailAccountDo.getSmtp());
        prop.setProperty("mail.transport.protocol", "smtp");
        prop.setProperty("mail.smtp.auth", "true");

        // 动态设置端口号和加密方式
        if (mailAccountDo.getPort() != null && !mailAccountDo.getPort().isEmpty()) {
            int port = Integer.parseInt(mailAccountDo.getPort());
            prop.setProperty("mail.smtp.port", mailAccountDo.getPort());
            prop.setProperty("mail.smtp.socketFactory.port", mailAccountDo.getPort());

            if (port == 587) {
                // 如果端口号为 587，则启用 TLS 加密
                prop.setProperty("mail.smtp.starttls.enable", "true");
                prop.setProperty("mail.smtp.starttls.required", "true");
            } else if (port == 465) {
                // 如果端口号为 465，则使用 SSL 加密
                prop.setProperty("mail.smtp.socketFactory.class", SSL_FACTORY);
                prop.setProperty("mail.smtp.socketFactory.fallback", "false");
            }
        } else {
            // 默认使用 SSL 加密（端口 465）
            prop.setProperty("mail.smtp.port", "465");
            prop.setProperty("mail.smtp.socketFactory.port", "465");
            prop.setProperty("mail.smtp.socketFactory.class", SSL_FACTORY);
            prop.setProperty("mail.smtp.socketFactory.fallback", "false");
        }


        //使用JavaMail发送邮件的5个步骤
        //1、创建session
        Session session = Session.getInstance(prop);
        //开启Session的debug模式，这样就可以查看到程序发送Email的运行状态
        session.setDebug(true);
        return session;
    }

    @Override
    public Transport initRakutenMailTransport(Session session) {
        return initRakutenMailTransport(session, "369266", "NJN1PK8kgj");
    }

    @Override
    public Transport initRakutenMailTransport(Session session, String id, String key) {
        //2、通过session得到transport对象
        Transport ts = null;
        try {
            ts = session.getTransport();
            //3、使用邮箱的用户名和密码连上邮件服务器，发送邮件时，发件人需要提交邮箱的用户名和密码给smtp服务器，用户名和密码都通过验证之后才能够正常发送邮件给收件人。
            ts.connect("sub.fw.rakuten.ne.jp", id, key);
        } catch (NoSuchProviderException e) {
            e.printStackTrace();
        } catch (MessagingException e) {
            e.printStackTrace();
        }
        return ts;
    }

    @Override
    public Session initRakutenMailSession() {
        Properties prop = new Properties();
        final String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory";
        prop.setProperty("mail.host", "sub.fw.rakuten.ne.jp");//这里设置了用qq邮箱发邮件
        prop.setProperty("mail.transport.protocol", "smtp");
        prop.setProperty("mail.smtp.auth", "true");
        //邮箱发送服务器端口,这里设置为465端口
        prop.setProperty("mail.smtp.port", "587");
        prop.setProperty("mail.smtp.socketFactory.port", "587");
        //使用JavaMail发送邮件的5个步骤
        //1、创建session
        Session session = Session.getInstance(prop);
        //开启Session的debug模式，这样就可以查看到程序发送Email的运行状态
        session.setDebug(true);
        return session;
    }

    @Override
    public Transport initMailTransport(Session session, SendMailReq req) {

        //2、通过session得到transport对象
        Transport ts = null;
        try {
            ts = session.getTransport();
            //3、使用邮箱的用户名和密码连上邮件服务器，发送邮件时，发件人需要提交邮箱的用户名和密码给smtp服务器，用户名和密码都通过验证之后才能够正常发送邮件给收件人。


            String mailNo = req.getUser();
            String password = req.getPassword();

           // ts.connect("smtp.exmail.qq.com", "ding@cloudkinto.com", "BkcYF5xn55fgb3c3");
            ts.connect(req.getSmtp(), mailNo, password);
        } catch (NoSuchProviderException e) {
            e.printStackTrace();
        } catch (MessagingException e) {
            e.printStackTrace();
        }
        return ts;
    }
@Override
    public Transport initMailTransport(MailAccountDo mailAccountDo,Session session) {

        //2、通过session得到transport对象
        Transport ts = null;
        try {
            ts = session.getTransport();
            //3、使用邮箱的用户名和密码连上邮件服务器，发送邮件时，发件人需要提交邮箱的用户名和密码给smtp服务器，用户名和密码都通过验证之后才能够正常发送邮件给收件人。


            /*String mailNo = "ding@cloudkinto.com";
            String password = "BkcYF5xn55fgb3c3";*/
            String mailNo=mailAccountDo.getUser();
            String password=mailAccountDo.getPassword();

            // ts.connect("smtp.exmail.qq.com", "ding@cloudkinto.com", "BkcYF5xn55fgb3c3");
            ts.connect(mailAccountDo.getSmtp(), mailNo, password);
        } catch (NoSuchProviderException e) {
            e.printStackTrace();
        } catch (MessagingException e) {
            e.printStackTrace();
        }
        return ts;
    }

    @Override
    public void sendEmailRakuten(Session session, Transport ts, String title, String content, String address, String from, String contentCodeType) {
        try {
            //4、创建邮件
            Message message = createRakutenMail(session, title, content, address, from, contentCodeType);
            //5、发送邮件
            ts.sendMessage(message, message.getAllRecipients());
        } catch (Exception e) {
            e.printStackTrace();
            logger.debug("发送給" + address + "的邮件失败");
        }
    }

    @Override
    public void sendEmailRakuten(Session session, Transport ts, String title, String content, String address, String from, String cc, String contentCodeType) {
        try {
            //4、创建邮件
            Message message = createRakutenMail(session, title, content, address, from, cc, contentCodeType);
            //5、发送邮件
            ts.sendMessage(message, message.getAllRecipients());
        } catch (Exception e) {
            e.printStackTrace();
            logger.debug("发送給" + address + "的邮件失败");
        }
    }

    @Override
    public void sendEmail(Session session, Transport ts, String title, String content, String from ,String address) throws Exception {

            //4、创建邮件
            Message message = createSimpleMail(session, title, content, from,address, "");
            //5、发送邮件
            ts.sendMessage(message, message.getAllRecipients());

    }

    @Override
    public void sendEmail(Session session, Transport ts, String title, String content,String from , String address, String cc)throws Exception  {

            //4、创建邮件
            Message message = createSimpleMail(session, title, content,from, address, cc);
            //5、发送邮件
            ts.sendMessage(message, message.getAllRecipients());

    }

    @Override
    public void sendFileEmail(Session session, Transport ts, String title, String fileTitle, String content, String contentType,String from , String address, String cc, String filePath) {
        try {
            //4、创建邮件
            Message message = createFileMail(session, title, fileTitle, content, contentType,from, address, cc, filePath);
            //5、发送邮件
            ts.sendMessage(message, message.getAllRecipients());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static MimeMessage createSimpleMail(Session session, String title, String content,String from, String address, String cc)
            throws Exception {
        //创建邮件对象
        MimeMessage message = new MimeMessage(session);
        //指明邮件的发件人
        message.setFrom(new InternetAddress(from));
        //指明邮件的收件人
        if (StringUtils.isNotBlank(address)) {
            if (address.contains(","))
                message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(address));
            else
                message.setRecipient(Message.RecipientType.TO, new InternetAddress(address));
        }
        if (StringUtils.isNotBlank(cc))
            message.setRecipients(Message.RecipientType.CC, InternetAddress.parse(cc));
        //邮件的标题
        message.setSubject(title);
        //邮件的文本内容
        message.setContent(content, "text/html;charset=UTF-8");
        //返回创建好的邮件对象
        return message;
    }


    public static MimeMessage createFileMail(Session session, String title, String fileTitle, String content, String from ,String address, String cc, String filePath)
            throws Exception {
        return createFileMail(session, title, fileTitle, content, "text/html;charset=UTF-8", address, cc, filePath);
    }

    public static MimeMessage createFileMail(Session session, String title, String fileTitle, String content, String contenType,String from , String address, String ccAddress, String filePath)
            throws Exception {
        //创建邮件对象
        MimeMessage message = new MimeMessage(session);
        //指明邮件的发件人
        message.setFrom(new InternetAddress(from));
        //指明邮件的收件人
        message.setRecipient(Message.RecipientType.TO, new InternetAddress(address));
        if (StringUtils.isNotBlank(ccAddress))
            message.setRecipients(Message.RecipientType.CC, InternetAddress.parse(ccAddress));
        //邮件的标题
        message.setSubject(title);
        //邮件的文本内容
        MimeMultipart multipart = new MimeMultipart();
        //设置邮件的文本内容
        MimeBodyPart contentPart = new MimeBodyPart();
        contentPart.setContent(content, contenType);
        multipart.addBodyPart(contentPart);
        //添加附件
        MimeBodyPart filePart = new MimeBodyPart();
        DataSource source = new FileDataSource(filePath);
        //添加附件的内容
        filePart.setDataHandler(new DataHandler(source));
        //添加附件的标题
        filePart.setFileName(MimeUtility.encodeText(fileTitle, "shift-JIS", null));
        multipart.addBodyPart(filePart);
        multipart.setSubType("mixed");
        //将multipart对象放到message中
        message.setContent(multipart, contenType);
        //返回创建好的邮件对象
        return message;
    }

    public static MimeMessage createRakutenMail(Session session, String title, String content, String address, String from, String contentCodeType)
            throws Exception {
        //创建邮件对象
        MimeMessage message = new MimeMessage(session);
        //指明邮件的发件人
        message.setFrom(new InternetAddress(from));
        //指明邮件的收件人
        message.setRecipient(Message.RecipientType.TO, new InternetAddress(address));
        message.setRecipient(Message.RecipientType.CC, new InternetAddress(from));
        //邮件的标题
        message.setSubject(title, contentCodeType.split("=")[1]);
        //邮件的文本内容
        message.setContent(content, contentCodeType);
        //返回创建好的邮件对象
        return message;
    }

    public static MimeMessage createRakutenMail(Session session, String title, String content, String address, String from, String cc, String contentCodeType)
            throws Exception {
        //创建邮件对象
        MimeMessage message = new MimeMessage(session);
        //指明邮件的发件人
        message.setFrom(new InternetAddress(from));
        //指明邮件的收件人
        message.setRecipient(Message.RecipientType.TO, new InternetAddress(address));
        if (StringUtils.isNotBlank(cc)) {
            if (cc.contains(","))
                message.setRecipients(Message.RecipientType.CC, InternetAddress.parse(cc));
            else
                message.setRecipient(Message.RecipientType.CC, new InternetAddress(cc));
        }

        //邮件的标题
        message.setSubject(title, contentCodeType.split("=")[1]);
        //邮件的文本内容
        message.setContent(content, contentCodeType);
        //返回创建好的邮件对象
        return message;
    }
}
